package lion.web.interceptors.cluster.session;

import java.util.Collections;
import java.util.Enumeration;

import javax.servlet.http.HttpSession;

import lion.dev.lang.MapJ;
import lion.framework.core.cache.CacheManager;
import lion.framework.core.cache.ICache;
import lion.framework.core.conf.Config;
import lion.framework.core.conf.ConfigManager;

/**
 * 集群session实现，将Httpsession与缓存session进行同步
 * 
 * <pre>
 * time   2013 2013年12月19日 下午4:55:30
 * mail   hl_0074@sina.com
 * </pre>
 * 
 * @author lion
 */
public class ClusteredSession extends ClusteredSessionWrapper {

	private MapJ map;
	private ICache sessionCache;
	private String sid;
	private boolean changed = false;
	private boolean stick;

	public ClusteredSession(String sid, HttpSession session) {

		super(session);
		this.sid = sid;
		Config config = ConfigManager.getConfig("framework");
		MapJ conf = config.getOne("framework.mvc.clustersession");

		String cacheName = conf.getString("cache");
		this.sessionCache = CacheManager.getCache(cacheName);
		this.stick = sessionCache.getBoolean("stick");

		if (!stick || session.isNew()) {
			this.map = (MapJ) sessionCache.get(sid);
			if (this.map == null) {
				this.map = new MapJ();
			}
			if (stick && session.isNew()) {
				for (String key : map.keySet()) {
					session.setAttribute(key, map.get(key));
				}
			}
		}
	}

	@Override
	public Object getAttribute(String key) {

		if (stick) { return this.httpSession.getAttribute(key); }
		return map.get(key);
	}

	@Override
	public Enumeration<String> getAttributeNames() {

		if (stick) { return this.httpSession.getAttributeNames(); }
		return Collections.enumeration(map.keySet());
	}

	@Override
	public void setAttribute(String key, Object value) {

		if (stick) {
			this.httpSession.setAttribute(key, value);
		} else {
			this.map.put(key, value);
		}
		changed = true;
	}

	@Override
	public void removeAttribute(String key) {

		if (stick) {
			this.httpSession.removeAttribute(key);
		} else {
			this.map.remove(key);
		}
		changed = true;
	}

	@Override
	public void invalidate() {

		if (stick) {
			this.httpSession.invalidate();
		}
		if (map != null) {
			map.clear();
		}
		sessionCache.remove(this.sid);
		changed = true;
	}

	public void sync() {

		if (!changed) { return; }
		if (stick) {
			this.map = new MapJ();
			for (String key : Collections.list(this.httpSession.getAttributeNames())) {
				this.map.put(key, this.httpSession.getAttribute(key));
			}
		}
		this.sessionCache.put(this.sid, this.map, this.httpSession.getMaxInactiveInterval());
	}
}
